import 'dart:async';

import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:ly_bluetooth/src/model/list_expend.dart';

import 'model/device_connect.dart';

class LyBleApi {
  LyBleApi._init();
  static LyBleApi? _instance;
  static LyBleApi _instanceMake() {
    _instance ??= LyBleApi._init();
    return _instance!;
  }

  static LyBleApi get instance => _instanceMake();
  // 默认连接的设备map
  var defaultConnectDeviceMap = <String, DeviceConnect>{};

  // 设备map
  var scanDeviceMap = <String, DeviceConnect>{};

  StreamSubscription<List<ScanResult>>? _streamSubscription;

  final _devices = <BluetoothDevice>[];
  final Map needReConnectMap = {};

  StreamController listenController = StreamController.broadcast();
  // 扫描蓝牙设备，返回设备列表
  Future<void> scanDevices(StreamController scanController) async {
    _streamSubscription = FlutterBluePlus.scanResults.listen((event) {
      _devices.addOrUpdataWhereSame(event.map((e) => e.device).toList(),
          (p0, p1) => p0.remoteId.str == p1.remoteId.str);

      scanController.add(_devices);
    }, cancelOnError: true, onError: (e) => scanController.add([]));
    await FlutterBluePlus.startScan(
        withServices: [], timeout: const Duration(seconds: 15));
  }

  setReConnectStatus(String deviceCode, bool reConnect) {
    needReConnectMap[deviceCode] = reConnect;
  }

  /// 停止蓝牙设备扫描
  Future<void> stopScan() async {
    await FlutterBluePlus.stopScan();
    await _streamSubscription?.cancel();
  }

  Future<void> connectToDevice(DeviceConnect deviceConnect) async {
    if (defaultConnectDeviceMap[deviceConnect.macId] != null &&
        needReConnectMap[deviceConnect.macId] != null) {
      return;
    }
    defaultConnectDeviceMap.putIfAbsent(
        deviceConnect.macId, () => deviceConnect);

    await deviceConnect.device?.connect();

//
    deviceConnect.device?.onServicesReset.listen((event) {
      _discoverServices(deviceConnect);
    });
    deviceConnect.connectionState.listen((event) {
      if (event == BluetoothConnectionState.connected) {
        scanDeviceMap[deviceConnect.macId] = deviceConnect;
        //连接成功
        _discoverServices(deviceConnect);
      } else if (event == BluetoothConnectionState.disconnected) {
        // 连接失败
        print("断开连接====================");
        scanDeviceMap.remove(deviceConnect.macId);
        if (defaultConnectDeviceMap.containsKey(deviceConnect.macId) &&
            needReConnectMap[deviceConnect.macId]) {
          Future.delayed(const Duration(seconds: 1), () {
            connectToDevice(deviceConnect);
          });
        }
      }
    }, onError: (e) {
      if (needReConnectMap[deviceConnect.macId]) {
        Future.delayed(const Duration(seconds: 1), () {
          connectToDevice(deviceConnect);
        });
      }
    });
  }

  //断开连接
  Future<void> closeDevice(String deviceCode) async {
    needReConnectMap[deviceCode] = false;
    if (scanDeviceMap.containsKey(deviceCode)) {
      DeviceConnect? deviceConnect = scanDeviceMap[deviceCode];
      await deviceConnect?.disconnect();
      scanDeviceMap.remove(deviceCode);
    }
  }

  //删除设备
  Future<void> delConnectDevice(String deviceCode) async {
    await closeDevice(deviceCode);
    defaultConnectDeviceMap.remove(deviceCode);
  }

  Future<void> _discoverServices(DeviceConnect deviceConnect) async {
    List<BluetoothService> serviceList =
        await deviceConnect.device?.discoverServices() ?? [];
    for (BluetoothService element in serviceList) {
      if (element.serviceUuid.toString() ==
          deviceConnect.serviceUuid.toString()) {
        for (BluetoothCharacteristic item in element.characteristics) {
          if (item.characteristicUuid.toString() ==
              deviceConnect.readUuid.toString()) {
            deviceConnect.readService = item;
          } else if (item.characteristicUuid.toString() ==
              deviceConnect.writeUuid.toString()) {
            deviceConnect.writeService = item;
          } else if (item.characteristicUuid.toString() ==
              deviceConnect.otherUuid.toString()) {
            deviceConnect.otherService = item;
          }
        }
      }
    }
    if (deviceConnect.readService != null && deviceConnect.readUuid != null) {
      _listenCharacteristic(deviceConnect);
    }
  }

  Future<void> _listenCharacteristic(DeviceConnect deviceConnect) async {
    if (deviceConnect.setNotify == true) {
      deviceConnect.writeService?.setNotifyValue(true);
    }
    deviceConnect.writeService?.onValueReceived.listen((event) {
      listenController.add(event);
    }, onError: (e) {});
  }

  Future<void> writeToDevice(
      DeviceConnect deviceConnect, List<int>? command) async {
    if (scanDeviceMap.containsKey(deviceConnect.macId) &&
        deviceConnect.writeService != null) {
      deviceConnect.writeService?.write(command ?? []);
    } else {
      print('~~~~~~~~~deviceConnect.code:${deviceConnect.macId}断开连接');
    }
  }
}
